﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Runtime.InteropServices;

namespace Sakura.Media.AviSynth.Native
{
	/// <summary>
	/// 表示一个视频帧。视频帧是视频缓冲区中的一个窗口。
	/// </summary>
	[StructLayout(LayoutKind.Sequential)]
	internal struct AvsVideoFrame
	{
		/// <summary>
		/// 视频帧的引用计数。
		/// </summary>
		public int RefCount;
		/// <summary>
		/// 视频帧的缓冲区。
		/// </summary>
		public IntPtr Buffer;
		public int Offset;
		public int Pitch;
		public int RowSize;
		public int Height;
		public int OffsetU;
		public int OffsetV;
		public int PitchUV;

		/// <summary>
		/// 获取指定平面的 Pitch 值。
		/// </summary>
		/// <param name="plane">要获取 Pitch 值的平面。</param>
		/// <returns>该平面对应的 Pitch 值。</returns>
		public int GetPitchForPlane(PlaneType plane)
		{
			switch (plane)
			{
				case PlaneType.U:
				case PlaneType.V:
					return this.PitchUV;
				default:
					return this.Pitch;
			}
		}

		/// <summary>
		/// 获取指定平面的宽度，以字节为单位。
		/// </summary>
		/// <param name="plane">要获取宽度的平面。</param>
		/// <returns>该平面对应的宽度。</returns>
		public int GetRowSizeForPlane(PlaneType plane)
		{
			switch (plane)
			{
				case PlaneType.U:
				case PlaneType.V:
					if (this.PitchUV != 0)
					{
						return this.RowSize >> 1;
					}
					else
					{
						return 0;
					}
				case PlaneType.UAligned:
				case PlaneType.VAligned:
					if (this.PitchUV != 0)
					{
						var r = ((this.RowSize + Constants.AvsFrameAlign - 1) & (~(Constants.AvsFrameAlign - 1))) >> 1;
						if (r < this.PitchUV)
						{
							return r;
						}
						else
						{
							return this.RowSize >> 1;
						}
					}
					else
					{
						return 0;
					}
				case PlaneType.YAligned:
					{
						var r = ((this.RowSize + Constants.AvsFrameAlign - 1) & (~(Constants.AvsFrameAlign - 1))) >> 1;
						if (r < this.PitchUV)
						{
							return r;
						}
						else
						{
							return this.RowSize >> 1;
						}
					}
				default:
					return this.RowSize;
			}
		}

		/// <summary>
		/// 获取指定平面的高度。
		/// </summary>
		/// <param name="plane">要获取高度的平面。</param>
		/// <returns>该平面对应的高度。</returns>
		public int GetHeightForPlane(PlaneType plane)
		{
			switch (plane)
			{
				case PlaneType.U:
				case PlaneType.V:
					if (this.PitchUV != 0)
					{
						return this.Height >> 1;
					}
					else
					{
						return 0;
					}
				default:
					return this.Height;
			}
		}

		public IntPtr ReadPtr
		{
			get
			{
				throw new NotImplementedException();
			}
		}
	}
}
